home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / c_dates.zip / C_DATES.C next >
Text File  |  1987-08-04  |  14KB  |  377 lines

  1. /************************************************************************/
  2. /*  (c)  1987 by James N. Seed,  Dallas, TX  -  all rights reserved.    */
  3. /*                                    */
  4. /*  Permission is granted to freely distribute and use this document    */
  5. /*  for whatever purpose provided that:                    */
  6. /*                                    */
  7. /*  A)    this copyright notice, in its entirety, including the author's    */
  8. /*    name (above) is not removed or altered, and            */
  9. /*                                    */
  10. /*  B)    it, and/or any or all of the algorithms it contains, is not    */
  11. /*    sold, distributed, or used in any form, FOR MONETARY PROFIT,    */
  12. /*    without the express written consent of the author, named above.    */
  13. /************************************************************************/
  14.  
  15. /************************************************************************/
  16. /*  All of these routines were written entirely in machine independant,    */
  17. /*  compiler independant, standard ( ANSI ) "C" language.        */
  18. /*                                    */
  19. /*  The only exceptions to the machine independance of the source occur    */
  20. /*  in "jtog" and "fulldte", because they assume the usage of the ASCII    */
  21. /*  character set.                            */
  22. /************************************************************************/
  23.  
  24. /************************************************************************/
  25. /*  Notes:  For those of you that don't already know, a "julian" date    */
  26. /*  =====   is simply the number of days that has transpired since    */
  27. /*        some arbitrary point in time.  For these routines, that    */
  28. /*        arbitrary point in time is 01/00/0000, or the 0th day A.D.    */
  29. /*        A "gregorian" date is simply a date expressed in terms of    */
  30. /*        the month, day, and year, which is what we use today.    */
  31. /*                                    */
  32. /*        The name "julian" comes from the creator of the original    */
  33. /*        concept, Julius Caesar, and I think the name "gregorian"    */
  34. /*        comes from Pope Gregory, who sanctified the continued use    */
  35. /*        of the original Pagan concept, although I'm not sure...    */
  36. /*                                    */
  37. /*        All of these routines assume that year 0000 is a leap year.    */
  38. /*                                    */
  39. /*        In the interest of portability, I have not declared any    */
  40. /*        "unsigned long" variable types, because some compilers do    */
  41. /*        not support it.  The "docs in the box" for each routine,    */
  42. /*        however, specify which long integers should be unsigned,    */
  43. /*        so you can go ahead and change the source to reflect this    */
  44. /*        if you like.  It will only make a difference if you are    */
  45. /*        working with HUGE date numbers ( ie: past year 9999 ) or    */
  46. /*        in the ( unlikely? ) event that you erroneously input a    */
  47. /*        negative julian date. ( a definite no no )            */
  48. /************************************************************************/
  49.  
  50. /************************************************************************/
  51. /*                *** gtoj.c ***                */
  52. /*                                    */
  53. /* This function converts a gregorian date, in the ( month, day, year )    */
  54. /* format, into its respective julian, or day number, equivalent.    */
  55. /* ( 1 = 1st day AD )                            */
  56. /*                                    */
  57. /* The legal input values, in their proper order, are:            */
  58. /*                                    */
  59. /*    month   =  1   to    12            ( unsigned int )    */
  60. /*    day     =  1   to    31            ( unsigned int )    */
  61. /*    year    =  0   to  9999            ( unsigned int )    */
  62. /*                                    */
  63. /* The return value of the function is the julian day number        */
  64. /* expressed as    an unsigned long integer.                */
  65. /*                                    */
  66. /************************************************************************/
  67.  
  68. long gtoj( m, d, y )
  69.  
  70. unsigned int m, d, y;
  71.  
  72. {
  73.     y += ( m += 9 ) / 12 + 399;
  74.     m %= 12;
  75.  
  76.     return ( (long)y*365 + y/4 - y/100 + y/400 + (153*m+2)/5 + d - 146037 );
  77. }
  78.  
  79. /************************************************************************/
  80. /*                *** jtog.c ***                */
  81. /*                                    */
  82. /* This function converts a julian day number ( 1 = 1st day AD ), into    */
  83. /* either a gregorian date character string, in any one of the four    */
  84. /* formats described below, or an array of three integers representing    */
  85. /* the month, day, and year, respectively, of the equivalent gregorian    */
  86. /* date.  Storage for the output is provided by the calling routine.    */
  87. /*                                    */
  88. /* The input values, in their proper order, are:            */
  89. /*                                    */
  90. /*  1.  the julian date to be converted,          ( unsigned long )    */
  91. /*                                    */
  92. /*  2.  a pointer to the output array,              ( char * )    */
  93. /*                                    */
  94. /*  3.  the format code ( described below )                */
  95. /*    specifying the desired output format.          ( unsigned int )    */
  96. /*                                    */
  97. /* The format codes are defined as follows:                */
  98. /*                                    */
  99. /*   CODE            - EXPLANATION -                */
  100. /*                                    */
  101. /*     0  -  output array will hold three integers defined as:        */
  102. /*                                    */
  103. /*            array[0] = month    (   mm )        */
  104. /*            array[1] = day        (   dd )        */
  105. /*            array[2] = year        ( yyyy )        */
  106. /*                                    */
  107. /*         If this format option is used, a type cast will have to    */
  108. /*         be performed on the output pointer to convert it to the    */
  109. /*         appropriate pointer type. ( see example below )        */
  110. /*                                    */
  111. /*     1  -  output string will hold a character string in the        */
  112. /*         format "mmddyy"      ( minimum - char string[7] )        */
  113. /*                                    */
  114. /*     2  -  output string will hold a character string in the        */
  115. /*         format "mmddyyyy"      ( minimum - char string[9] )        */
  116. /*                                    */
  117. /*     3  -  output string will hold a character string in the        */
  118. /*         format "mm/dd/yy"      ( minimum - char string[9] )        */
  119. /*                                    */
  120. /*     4  -  output string will hold a character string in the        */
  121. /*         format "mm/dd/yyyy"  ( minimum - char string[11] )        */
  122. /*                                    */
  123. /*   NOTE -  input of any format code not listed above will be        */
  124. /*         interpreted as code 0.                    */
  125. /*                                    */
  126. /*   The function returns a character pointer to the output array.    */
  127. /*    ______________________________________________________________    */
  128. /*   |           *** example of integer array output ***        |    */
  129. /*   |                                    |    */
  130. /*   |  int    month, dte_array[3];                    |    */
  131. /*   |  long    julian = 548784;                    |    */
  132. /*   |                                    |    */
  133. /*   |  month = ( (int *)jtog( julian, (char *)dte_array, 0 ) )[0]; |    */
  134. /*   |______________________________________________________________|    */
  135. /*                                    */
  136. /*   WARNING -  the output array pointed to must be dimensioned        */
  137. /*        accordingly or a memory overwrite will occur.        */
  138. /************************************************************************/
  139.  
  140. char *jtog( julian, date, fmt )
  141.  
  142. long julian;
  143. char *date;
  144. unsigned int fmt;
  145.  
  146. {
  147.     int  month, day, year, i;
  148.     long numdte, indx = !( fmt & 1 ) * 9900 + 100;
  149.  
  150.     year    = ( julian += 146037 ) * 400 / 146097;
  151.     julian -= (long)year*365 + year/4 - year/100 + year/400;
  152.  
  153.     if ( !julian ) julian = 365 + !( year % 4 ), --year;
  154.  
  155.     year += ( month = ( day = (int)julian * 5 - 3 ) / 153 + 2 ) / 12 - 400;
  156.     month = month % 12 + 1;
  157.     day   = day % 153 / 5 + 1;
  158.  
  159.     if ( fmt && fmt < 5 )
  160.     {
  161.          numdte = (long)month * 100 * indx + day * indx + year % indx;
  162.          for ( indx *= 10000, i = 0; indx > 1; ++i )
  163.            date[i] = ( fmt > 2 && ( i == 2 || i == 5 ) )  ?  '/'
  164.                : (char)( numdte / ( indx /= 10 ) % 10 + 48 );
  165.          date[i] = '\0';
  166.     }
  167.     else
  168.     {
  169.          ((int *)date)[0] = month;
  170.          ((int *)date)[1] = day;
  171.          ((int *)date)[2] = year;
  172.     }
  173.  
  174.     return( date );
  175. }
  176.  
  177. /************************************************************************/
  178. /*                *** dow.c ***                */
  179. /*                                    */
  180. /* This function returns the numerical day-of-week of a julian        */
  181. /* date, input as an unsigned long integer.                */
  182. /*                                    */
  183. /* The return value of the function is the day of the week expressed    */
  184. /* as an unsigned integer value, and is enumerated as follows:        */
  185. /*                                    */
  186. /*    Sunday    -  0                            */
  187. /*    Monday    -  1            Thursday  -  4            */
  188. /*    Tuesday   -  2            Friday    -  5            */
  189. /*    Wednesday -  3            Saturday  -  6            */
  190. /*                                    */
  191. /************************************************************************/
  192.  
  193. int dow( julian )
  194.  
  195. long julian;
  196.  
  197. {
  198.     return( (int)( ( julian + 5 ) % 7 ) );
  199. }
  200.  
  201. /************************************************************************/
  202. /*                *** fulldte.c ***            */
  203. /*                                    */
  204. /* This function converts a julian day number ( 1 = 1st day AD ),    */
  205. /* into an equivalent gregorian date descriptive phraze of the form:    */
  206. /*                                    */
  207. /*    "Wednesday September 16, 1987"        ( example )        */
  208. /*                                    */
  209. /* The input values, in their proper order, are:            */
  210. /*                                    */
  211. /*  1.  the julian date to be converted              ( unsigned long )    */
  212. /*                                    */
  213. /*  2.  a pointer to the output character string.     ( char * )    */
  214. /*                                    */
  215. /* The length, in ASCII characters, of the output string is returned    */
  216. /* by the function upon completion, expressed as an unsigned integer.    */
  217. /*                                    */
  218. /* WARNING - the character string pointed to must be dimensioned to    */
  219. /*         at least 29 characters, or a memory overwrite may occur.    */
  220. /*                                    */
  221. /************************************************************************/
  222.  
  223. int fulldte( julian, dtestr )
  224.  
  225. long julian;
  226. char *dtestr;
  227.  
  228. {
  229.     static char *daynme[7]  =  {  "Sunday",    "Monday",   "Tuesday",
  230.                       "Wednesday", "Thursday", "Friday",
  231.                       "Saturday"              };
  232.     static char *mosnme[12] =  {  "January", "February", "March",
  233.                       "April",   "May",      "June",
  234.                       "July",    "August",   "September",
  235.                       "October", "November", "December"   };
  236.  
  237.     static char **text[2] = { daynme, mosnme };
  238.  
  239.     int i, j, k, strt, dtearr[4];
  240.  
  241.     dtearr[0] = dow( julian );
  242.     jtog( julian, (char *)&dtearr[1], 0 );
  243.     --dtearr[1];
  244.  
  245.     for ( i = j = k = 0; i < 2; k = 0, ++i )
  246.     {
  247.           while ( text[i][dtearr[i]][k] )
  248.               dtestr[j++] = text[i][dtearr[i]][k++];
  249.           dtestr[j++] = ' ';
  250.     }
  251.  
  252.     for ( strt = 0, i = 2; i < 4; ++i )
  253.     {
  254.           for ( k = 1000; k; dtearr[i] %= k, k /= 10 )
  255.           {
  256.             if ( strt = strt || dtearr[i] / k )
  257.              dtestr[j++] = (char)( dtearr[i] / k + 48 );
  258.           }
  259.  
  260.           if ( i == 2 ) dtestr[j++] = ',';
  261.  
  262.           dtestr[j++] = ' ';
  263.     }
  264.  
  265.     dtestr[--j] = '\0';
  266.  
  267.     return( j );
  268. }
  269.  
  270. /************************************************************************/
  271. /*                *** daycnt.c ***            */
  272. /*                                    */
  273. /* This function returns the number of days of the specified type that    */
  274. /* exist between the two julian dates input, expressed as an signed    */
  275. /* long integer.                            */
  276. /*                                    */
  277. /* The input values to the function, in their proper order, are:    */
  278. /*                                    */
  279. /*  1.  the beginning julian date              ( unsigned long )    */
  280. /*                                    */
  281. /*  2.  the ending julian date                  ( unsigned long )    */
  282. /*                                    */
  283. /*  3.  the numerical code representing the type            */
  284. /*    of days    to be counted ( described below )     ( unsigned int )    */
  285. /*                                    */
  286. /* The following is a list of the codes used to define the        */
  287. /* type of days that are to be counted:                    */
  288. /*                                    */
  289. /*   CODE        - EXPLANATION -                    */
  290. /*                                    */
  291. /*     0  -  all days                            */
  292. /*                                    */
  293. /*     1  -  all days excluding Sundays                    */
  294. /*                                    */
  295. /*     2  -  all days excluding weekends ( Saturdays and Sundays )    */
  296. /*                                    */
  297. /*   NOTE -  input of any code not listed above will be            */
  298. /*         interpreted as code 0.                    */
  299. /*                                    */
  300. /************************************************************************/
  301.  
  302. long daycnt( juldt1, juldt2, excl )
  303.  
  304. long juldt1, juldt2;
  305. unsigned int excl;
  306.  
  307. {
  308.     int  eff = 7 - ( excl = excl > 2 ? 0 : excl );
  309.  
  310.     if ( !excl-- ) return( juldt2 - juldt1 );
  311.  
  312.     if ( juldt1 > juldt2 ) return( -daycnt( juldt2, juldt1, ++excl ) );
  313.     else
  314.     {
  315.          juldt1 -= !dow( juldt1 ) + ( excl && !( dow( juldt1 ) % 6 ) );
  316.          juldt2 -= !dow( juldt2 ) + ( excl && !( dow( juldt2 ) % 6 ) );
  317.     }
  318.  
  319.     return( ( juldt2 - juldt1 ) / 7 * eff +
  320.         ( dow( juldt2 ) - dow( juldt1 ) + eff ) % eff );
  321. }
  322.  
  323. /************************************************************************/
  324. /*                *** newdate.c ***            */
  325. /*                                    */
  326. /* This function returns a new julian date, expressed as an unsigned    */
  327. /* long integer, arrived at by adding a    specified number of days of a    */
  328. /* specified type to the starting julian date input.            */
  329. /*                                    */
  330. /* In short, it adds days to a date to get a new date.            */
  331. /*                                    */
  332. /* The input values to the function, in their proper order, are:    */
  333. /*                                    */
  334. /*  1.  the beginning julian date              ( unsigned long )    */
  335. /*                                    */
  336. /*  2.  the number of days to be added              ( signed   long )    */
  337. /*                                    */
  338. /*  3.  the numerical code representing the type            */
  339. /*    of days    to be added ( described below )          ( unsigned int )    */
  340. /*                                    */
  341. /* The following is a list of the codes used to define the        */
  342. /* type of days that are to be added to the start date:            */
  343. /*                                    */
  344. /*   CODE        - EXPLANATION -                    */
  345. /*                                    */
  346. /*     0  -  weekdays and weekends (all days)                */
  347. /*                                    */
  348. /*     1  -  weekdays and Saturdays only (Sundays skipped over)        */
  349. /*                                    */
  350. /*     2  -  weekdays only (weekends skipped over)            */
  351. /*                                    */
  352. /*   NOTE -  input of any code not listed above will be            */
  353. /*         interpreted as code 0.                    */
  354. /*                                    */
  355. /************************************************************************/
  356.  
  357. long newdate( juldte, days, incl )
  358.  
  359. long juldte, days;
  360. unsigned int incl;
  361.  
  362. {
  363.     int eff = 7 - ( incl = incl > 2 ? 0 : incl ), rvrse = 0;
  364.  
  365.     if ( !incl-- ) return( juldte + days );
  366.  
  367.     if ( days < 0 )
  368.     {
  369.          rvrse   = eff + 1;
  370.          juldte += !dow( juldte ) + 2 * ( incl && !( 6 - dow( juldte ) ) );
  371.     }
  372.     else juldte -= !dow( juldte ) + ( incl && !( dow( juldte ) % 6 ) );
  373.  
  374.     return( juldte + days / eff * 7 + days % eff + ++incl *
  375.           ( ( dow( juldte ) + days % eff - rvrse ) / ( eff + 1 ) ) );
  376. }
  377.